package Retrier;
require v5.8.6;
our $VERSION 0.1001;
use Exporter 'import';
our @EXPORT_OK = qw(retrier);

sub retrier {
  my( $itr ) = @_;
  sub {
    my( $sub ) = @_;
    
  };
}

1;
__END__

=head1 NAME

Retrier - Retry subref execution if it dies with intervals provided by an iterator.

=head SYNOPSIS

  use Retrier 'retrier';
  use Iterator::Misc;
  use Iterator::Util;
  use Parallel::SubArray 'par';

  my $subref = sub{
    $i++;
    die 'Some Error' if $i < 4;
    return $i;
  };

  ####################################################################
  # infinite retries

  my $i = 0;
  my $result = retrier( fibonacci() )->( $subref );

  # try 1, wait 1s, try 2, wait 1s, try 3, wait 2s, try 4, success
  # waited 1+1+2 = 3s
  # tried 4 times

  $result == 4;

  ####################################################################
  # finite retries

  $i = 0;
  $result = eval{ retrier( ihead( 2, fibonacci() ) )->( $subref ) };

  # try 1, wait 1s, try 2, wait 1s, try 3, failure
  # waited 1+1 = 2s
  # tried 3 times

  $result == undef;
  $@ ~= /Some Error/;

  ####################################################################
  # parallel infinite retries with a timeout

  my $r = retrier( fibonacci() );

  # iterator will be reused because we are copy-on-write forking

  $i = 0;
  my $result_arrayref = par(10)->([
    sub{ $r->(sub{                     [1]  }) },
    sub{ $r->(sub{                     die  }) },
    sub{ $r->(sub{ $i++; $i>4 ? [$i] : die  }) },
  ]);

  # timeout after 10 seconds because second routine keeps retrying
  # forever

  $result_arrayref == [
    [1],
    undef,
    [5], # try 1, wait 1, try 2, wait 1, try 3, wait 2, try 4, wait 3,
         # try 5, success. waited 1+1+2+3 = 7s
  ];

  # btw, $r has not been used here yet, thanks to forking. See
  # Parallel::SubArray

=cut
